/**
 * 
 */
package com.comp6231.replica3;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Hashtable;

import org.omg.CORBA.ORB;

import com.comp6231.common.Request;
import com.comp6231.coordinator.Coordinator;
import com.comp6231.replica3.RequestParser;
import com.comp6231.replica3.common.RecordStatus;
import com.comp6231.replica3.common.police_station_idl.StationServerInterface;
import com.comp6231.replica3.common.police_station_idl.StationServerInterfaceHelper;
import com.comp6231.replica3.server.ServerStarter;

/**
 * @author Farzana Alam
 * 
 */
public class CoordinatorReplica3 extends Coordinator {

	private StationServerInterface spvmServer;
	private StationServerInterface splServer;
	private StationServerInterface spbServer;

	public CoordinatorReplica3(String hostName, String UDPPort,
			String controlUDPPort, String replicaName, int replicaID,
			Hashtable<String, String[]> coordinatorReplicaList,
			Hashtable<String, String[]> frontEndList) {
		super(hostName, UDPPort, controlUDPPort, replicaName, replicaID,
				coordinatorReplicaList, frontEndList);
		new Thread(new ServerStarter()).start();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		readServers();
	}

	@Override
	public String invokeMethod(Request request) {
		RequestParser reqParser = new RequestParser(request.getOperation(),
				request.getOperationArguments());
		return callLocalServerMethod(request, reqParser, request.getOperation());
	}

	private void readServers() {
		ORB orb = ORB.init(new String[] {}, null);

		spvmServer = readServerObjects(orb, "spvm");
		splServer = readServerObjects(orb, "spl");
		spbServer = readServerObjects(orb, "spb");
	}

	/**
	 * read CORBA object from file
	 * 
	 * @param orb
	 * @param name
	 * @return
	 */
	private StationServerInterface readServerObjects(ORB orb, String name) {
		BufferedReader br;
		try {
			br = new BufferedReader(new FileReader(System.getProperty("user.dir")
					+ "/src/com/comp6231/replica3/server"
					+ "/" + name + ".ior"));
			String ior = br.readLine();
			br.close();

			org.omg.CORBA.Object o = orb.string_to_object(ior);

			return StationServerInterfaceHelper.narrow(o);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private String callLocalServerMethod(Request request,
			RequestParser reqParser, String operation) {

		StationServerInterface server = null;

		if (reqParser.getBadgeID() != null) {
			if (reqParser.getBadgeID().startsWith("SPVM")) {
				server = spvmServer;
			} else if (reqParser.getBadgeID().startsWith("SPL")) {
				server = splServer;
			} else if (reqParser.getBadgeID().startsWith("SPB")) {
				server = spbServer;
			} else {
				// TODO : raise error
			}
		} else {
			// TODO : raise error
		}

		int status = 0;

		if (reqParser.getStatus() != null) {
			if (reqParser.getStatus().equalsIgnoreCase("captured")) {
				status = RecordStatus.Captured.ordinal();
			} else if (reqParser.getStatus().equalsIgnoreCase("otr")) {
				status = RecordStatus.OnTheRun.ordinal();
			} else if (reqParser.getStatus().equalsIgnoreCase("found")) {
				status = RecordStatus.Found.ordinal();
			} else if (reqParser.getStatus().equalsIgnoreCase("missing")) {
				status = RecordStatus.Missing.ordinal();
			}
		}

		StringBuilder result = new StringBuilder();
		String locallyProcessedResult = "Success";
		String replyFromServer = null;

		switch (operation.trim().toUpperCase()) {
		case "CREATECRECORD":
			replyFromServer = String
					.valueOf(server.createCRecord(reqParser.getFirstName(),
							reqParser.getLastName(),
							reqParser.getDescription(), status,
							reqParser.getBadgeID()));
			replyFromServer = (replyFromServer.equalsIgnoreCase("true") ? "Success"
					: "Fail");
			break;
		case "CREATEMRECORD":
			replyFromServer = String
					.valueOf(server.createMRecord(reqParser.getFirstName(),
							reqParser.getLastName(), reqParser.getAddress(),
							reqParser.getLastDate(),
							reqParser.getLastLocation(), status,
							reqParser.getBadgeID()));
			replyFromServer = (replyFromServer.equalsIgnoreCase("true") ? "Success"
					: "Fail");
			break;
		case "GETRECORDCOUNTS":
			replyFromServer = server.getRecordsCount((short) 0,
					reqParser.getBadgeID());
			break;
		case "EDITRECORD":
			replyFromServer = String.valueOf(server.editCRecord(
					reqParser.getLastName(), reqParser.getRecordID(), status,
					reqParser.getBadgeID()));
			replyFromServer = (replyFromServer.equalsIgnoreCase("true") ? "Success"
					: "Fail");
			break;
		case "TRANSFERRECORD":
			replyFromServer = String.valueOf(server.transferRecord(
					reqParser.getBadgeID(), reqParser.getRecordID(),
					reqParser.getRemoteStationServerName()));
			replyFromServer = (replyFromServer.equalsIgnoreCase("true") ? "Success"
					: "Fail");
			break;
		default:
			locallyProcessedResult = "Fail";
			break;
		}

		if (replyFromServer == null) {
			replyFromServer = "";
			locallyProcessedResult = "Fail";
		}
		result.append(locallyProcessedResult + " ## ").append(replyFromServer);

		if (locallyProcessedResult.equalsIgnoreCase("Success")) {
			System.out
					.println(request.getRequestID() + " is processed locally");
			request.setLocallyProcessed(true);
		}

		return result.toString();
	}

}
